package edu.ipccenter.toster.ejb;

import com.sun.xml.ws.api.tx.at.Transactional;
import edu.ipccenter.toster.*;
import java.math.BigInteger;
import java.util.Collection;
import java.util.HashSet;

import edu.ipccenter.toster.jpa.JPATestCase;
import edu.ipccenter.toster.jpa.JPATestSuite;
import java.util.*;
import javax.ejb.EJB;
import javax.ejb.Stateful;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

@Stateful
@Transactional
@TransactionAttribute(TransactionAttributeType.REQUIRED )
public class SuiteBean implements Suite {
    
    @EJB
    private SuiteUtils sub;
    @EJB
    private TestCaseUtils tcu;
    
   
       
        
         @PersistenceContext(unitName="TosterPU")
         private EntityManager em;
    
	private JPATestSuite testsuite;
    
	private Collection<Suite> children = new HashSet<Suite>();
    	
	
        @Override
        public void setSuite(JPATestSuite ts) {
        testsuite = ts;
    }
        
	@Override
	public String getName() {
               if(testsuite == null) return null;
		return testsuite.getSuiteName();
	}

	@Override
	public void setName(String name) {
            if(testsuite != null)
		testsuite.setSuiteName(name);
	}

	@Override
	public String getDescription() {
             if(testsuite == null) return null;
		return testsuite.getSuiteDesc();
	}

	@Override
	public void setDescription(String description) {
             if(testsuite != null)
		testsuite.setSuiteDesc(description);
	}

	@Override
	public BigInteger getID() {
             if(testsuite == null) return null;
		return testsuite.getSuiteId();
	}

	@Override
	public void setID(BigInteger id) {
             if(testsuite != null)
		testsuite.setSuiteId(id);
	}

	@Override
	public Suite getParent() {
         if(testsuite == null) return null;
         return sub.findByID(testsuite.getParentSuite()); 
	}

        
        
	@Override
	public void setParent(BigInteger id) {
             if(testsuite != null)
		testsuite.setParentSuite(id);
	}

        
        
        
        /**
         * This method returns all children of this Suite
         * @return Collection<Suite> children
         */
	@Override
	public Collection<Suite> getChildren() {
           if(testsuite == null) return null;
           children.clear(); 
           children(getID());
           return children;
	}
        
        /**
         * Returns the first floor children
         * @param elem_id - BigInteger ID of a start element
         * @return Collection<Suite> of first children
         */
        @Override
        public Collection<Suite> getFirstChildren(BigInteger elem_id){
            Collection<Suite> first_children = new HashSet<Suite>();
            
            Query q = em.createQuery("select c from JPATestSuite c where c.parentSuite = :id");
            q.setParameter("id", elem_id);
            List<JPATestSuite> list = q.getResultList();
            
            for(int i = 0; i < list.size(); i++){
                JPATestSuite jtestsuite = list.get(i);
                first_children.add(sub.findByID(jtestsuite.getSuiteId()));
                
            }
         return first_children;
            
        }
        
        //рекурсия вглубь дерева
        private void children(BigInteger id){
                 Collection<Suite> first = getFirstChildren(id);
                 Iterator it = first.iterator();
                 while(it.hasNext()){
                 Suite elem = (Suite) it.next();
                 children.add(elem);
                 children(elem.getID());
                 }
             }
        /**
         * This method returns TestCases which correspond only to this Suite
         * @return 
         */
	@Override
	public Collection<Name> getTestCases() {
		Collection<Name> names = new HashSet<Name>();
		
                Collection<JPATestCase> tcc = testsuite.getTestcase();
                Iterator it = tcc.iterator();
                while(it.hasNext()){
                    JPATestCase tc = (JPATestCase) it.next();
                    Name n = new Name();
                    n.setID(tc.getTcId());
                    n.setName(tc.getTcName());
                    names.add(n);
                }
		return names;
	}
         /**
         * This method returns TestCases which correspond to Suite suite 
         * 
         * @return Collection<Name> of all TestCase down to the tree
         */
	private Collection<Name> getAllTestCases(Suite suite) {
            
            if(suite == null) return null;
		Collection<Name> allTestCases = new HashSet<Name>();
                 children.clear(); 
                 children(suite.getID());
                 allTestCases.addAll(suite.getTestCases());
                 Iterator it = children.iterator();
                 
                 while(it.hasNext()){
                     Suite s = (Suite) it.next();
                     Collection<Name> col = s.getTestCases();
                     allTestCases.addAll(col);
                     }
		
					
		return allTestCases;
	}
	/**
         * This method returns all TestCases
         * @return 
         */
	@Override
	public Collection<Name> getAllTestCases() {
                if(testsuite == null) return null;
		Collection<Name> allTestCases;
		Suite s = sub.findByID(new BigInteger("1000"));
		
                allTestCases = getAllTestCases(s);
		return allTestCases;
	}

        
        
	@Override
	public void addTestCase(BigInteger id) {
            if(id == null) return;
            Set<JPATestCase> jtest_case = (Set<JPATestCase>) testsuite.getTestcase();
            jtest_case.add(tcu.findByID(id).getTestCase());
            em.merge(testsuite);
         
	}

	@Override
	public void removeTestCase(BigInteger id) {
            if(id == null) return;
            Set<JPATestCase> jtest_case = (Set<JPATestCase>) testsuite.getTestcase();
            jtest_case.remove(tcu.findByID(id).getTestCase());
            em.merge(testsuite);
		
	}

    @Override
    public JPATestSuite getSuite() {
        if(testsuite!=null) return testsuite;
        else return null;
    }

    
   
}
